﻿' ******************************************************************************
' ** 
' **  Yahoo! Managed
' **  Written by Marius Häusler 2011
' **  It would be pleasant, if you contact me when you are using this code.
' **  Contact: YahooFinanceManaged@gmail.com
' **  Project Home: http://code.google.com/p/yahoo-finance-managed/
' **  
' ******************************************************************************
' **  
' **  Copyright 2011 Marius Häusler
' **  
' **  Licensed under the Apache License, Version 2.0 (the "License");
' **  you may not use this file except in compliance with the License.
' **  You may obtain a copy of the License at
' **  
' **    http://www.apache.org/licenses/LICENSE-2.0
' **  
' **  Unless required by applicable law or agreed to in writing, software
' **  distributed under the License is distributed on an "AS IS" BASIS,
' **  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
' **  See the License for the specific language governing permissions and
' **  limitations under the License.
' ** 
' ******************************************************************************


Namespace YahooManaged.Finance.API

    ''' <summary>
    ''' Provides methods for downloading sectors, industries and company IDs.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class MarketDownload
        Inherits Base.Download

        Friend ReadOnly mFinanceHelper As New FinanceHelper
        Private mXmlParser As New ImportExport.XML
        Private mDefaultCulture As New Globalization.CultureInfo("en-US")

        ''' <summary>
        ''' Raises if an asynchronous download of sectors completes.
        ''' </summary>
        ''' <param name="sender">The event raising object</param>
        ''' <param name="ea">The event args of the asynchronous download</param>
        ''' <remarks></remarks>
        Public Event AsyncDownloadSectorsCompleted(ByVal sender As Base.Download, ByVal ea As SectorsDownloadCompletedEventArgs)
        ''' <summary>
        ''' Raises if an asynchronous download of industries completes.
        ''' </summary>
        ''' <param name="sender">The event raising object</param>
        ''' <param name="ea">The event args of the asynchronous download</param>
        ''' <remarks></remarks>
        Public Event AsyncDownloadIndustriesCompleted(ByVal sender As Base.Download, ByVal ea As IndustriesDownloadCompletedEventArgs)

        ''' <summary>
        ''' Downloads all available sectors and its industry IDs
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function DownloadAllSectors() As SectorResponse
            Return Me.DownloadSectors(Nothing)
        End Function
        ''' <summary>
        ''' Downloads sectors and its industry IDs with passed names.
        ''' </summary>
        ''' <param name="sectors">The names of the sectors</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function DownloadSectors(ByVal sectors As IEnumerable(Of Sector)) As SectorResponse
            Return Me.ToSectorResponse(MyBase.DownloadStream(Me.DownloadURLSector(mFinanceHelper.SectorEnumToArray(sectors))))
        End Function
        ''' <summary>
        ''' Downloads industries and its company IDs with passed IndustryData.
        ''' </summary>
        ''' <param name="industries">The industries</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function DownloadIndustries(ByVal industries As IEnumerable(Of IndustryData)) As IndustryResponse
            Dim lst As New List(Of Industry)
            If industries IsNot Nothing Then
                For Each ind As IndustryData In industries
                    lst.Add(ind.ID)
                Next
            End If
            If lst.Count = 0 Then Throw New ArgumentNullException("industries", "The passed list is empty.")
            Return Me.ToIndustryResponse(MyBase.DownloadStream(Me.DownloadURLIndustry(lst.ToArray)))
        End Function
        ''' <summary>
        ''' Downloads industries and its company IDs with passed IDs.
        ''' </summary>
        ''' <param name="industryIDs">The IDs of the industries</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function DownloadIndustries(ByVal industryIDs As IEnumerable(Of Industry)) As IndustryResponse
            Dim ids() As Industry = mHelper.EnumToArray(industryIDs)
            If ids.Length = 0 Then Throw New ArgumentNullException("industryIDs", "The passed list is empty.")
            Return Me.ToIndustryResponse(MyBase.DownloadStream(Me.DownloadURLIndustry(ids)))
        End Function

        ''' <summary>
        ''' Starts an asynchronous download of all available sectors and its industry IDs.
        ''' </summary>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Sub DownloadAllSectorsAsync(Optional ByVal userArgs As Object = Nothing)
            Me.DownloadSectorsAsync(Nothing, userArgs)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of sectors and its industry IDs with the passed names
        ''' </summary>
        ''' <param name="sectors">The names of the sectors</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Sub DownloadSectorsAsync(ByVal sectors As IEnumerable(Of Sector), Optional ByVal userArgs As Object = Nothing)
            Dim args As New SectorAsyncDownloadArgs(userArgs, mHelper.EnumToArray(sectors))
            MyBase.DownloadStreamAsync(Me.DownloadURLSector(mFinanceHelper.SectorEnumToArray(sectors)), args)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of industries with passed IndustryData
        ''' </summary>
        ''' <param name="industries">The industries</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>m
        Public Sub DownloadIndustriesAsync(ByVal industries As IEnumerable(Of IndustryData), Optional ByVal userArgs As Object = Nothing)
            Dim lst As New List(Of Industry)
            If industries IsNot Nothing Then
                For Each ind As IndustryData In industries
                    lst.Add(ind.ID)
                Next
            End If
            Me.DownloadIndustriesAsync(lst.ToArray, userArgs)
        End Sub
        ''' <summary>
        ''' Starts an asynchronous download of industries with passed IDs
        ''' </summary>
        ''' <param name="industryIDs">The IDs of the industries</param>
        ''' <param name="userArgs">Individual user argument</param>
        ''' <remarks></remarks>
        Public Sub DownloadIndustriesAsync(ByVal industryIDs As IEnumerable(Of Industry), Optional ByVal userArgs As Object = Nothing)
            Dim args As New IndustryAsyncDownloadArgs(userArgs, mHelper.EnumToArray(industryIDs))
            MyBase.DownloadStreamAsync(Me.DownloadURLIndustry(mHelper.EnumToArray(industryIDs)), args)
        End Sub

        ''' <summary>
        ''' Default constructor
        ''' </summary>
        ''' <remarks></remarks>
        Public Sub New()
        End Sub

        Private Sub DownloadAsync_Completed(ByVal sender As Base.Download, ByVal e As Base.StreamDownloadCompletedEventArgs) Handles MyBase.AsyncStreamDownloadCompleted
            If e IsNot Nothing AndAlso e.UserArgs IsNot Nothing Then
                If TypeOf e.UserArgs Is SectorAsyncDownloadArgs Then
                    Dim dlArgs As SectorAsyncDownloadArgs = DirectCast(e.UserArgs, SectorAsyncDownloadArgs)
                    Dim args As New SectorsDownloadCompletedEventArgs(dlArgs.UserArgs, Me.ToSectorResponse(e.Response), dlArgs.Sectors)
                    RaiseEvent AsyncDownloadSectorsCompleted(Me, args)

                ElseIf TypeOf e.UserArgs Is IndustryAsyncDownloadArgs Then
                    Dim dlArgs As IndustryAsyncDownloadArgs = DirectCast(e.UserArgs, IndustryAsyncDownloadArgs)
                    Dim args As New IndustriesDownloadCompletedEventArgs(dlArgs.UserArgs, Me.ToIndustryResponse(e.Response), dlArgs.Industries)
                    RaiseEvent AsyncDownloadIndustriesCompleted(Me, args)

                End If
            End If
        End Sub

        Private Function DownloadURLSector(ByVal names() As Sector) As String
            Dim whereClause As New Text.StringBuilder()
            If names IsNot Nothing AndAlso names.Length > 0 Then
                whereClause.Append("name in (")
                For Each sector As Sector In names
                    whereClause.Append(""""c)
                    whereClause.Append(sector.ToString.Replace("_", " "))
                    whereClause.Append(""",")
                Next
                whereClause.Remove(whereClause.Length - 1, 1)
                whereClause.Append(")"c)
            End If
            Return mHelper.YqlUrl("*"c, "yahoo.finance.sectors", whereClause.ToString, Nothing, False)
        End Function
        Private Function DownloadURLIndustry(ByVal indutryIDs() As Industry) As String
            If indutryIDs IsNot Nothing AndAlso indutryIDs.Length > 0 Then
                Dim whereClause As New Text.StringBuilder()
                whereClause.Append("id in (")
                For Each id As String In indutryIDs
                    whereClause.Append(""""c)
                    whereClause.Append(CInt(id).ToString)
                    whereClause.Append(""",")
                Next
                whereClause.Remove(whereClause.Length - 1, 1)
                whereClause.Append(")"c)
                Return mHelper.YqlUrl("*"c, "yahoo.finance.industry", whereClause.ToString, Nothing, False)
            Else
                Return String.Empty
            End If
        End Function

        Private Function ToSectorResponse(ByVal resp As Base.StreamResponse) As SectorResponse
            Dim sectors As New List(Of SectorData)
            Dim culture As New Globalization.CultureInfo("en-US")
            Dim results = mHelper.GetResultsFromXml(resp.Result, "sector")
            For Each node In results
                Dim s As SectorData = mXmlParser.ToSector(node, culture)
                If s IsNot Nothing Then sectors.Add(s)
            Next
            Return New SectorResponse(resp.Connection, sectors.ToArray)
        End Function
        Private Function ToIndustryResponse(ByVal resp As Base.StreamResponse) As IndustryResponse
            Dim industries As New List(Of IndustryData)
            Dim culture As New Globalization.CultureInfo("en-US")
            Dim results = mHelper.GetResultsFromXml(resp.Result, "industry")
            For Each node In results
                Dim c As IndustryData = mXmlParser.ToIndustry(node, culture)
                If c IsNot Nothing Then industries.Add(c)
            Next
            Return New IndustryResponse(resp.Connection, industries.ToArray)
        End Function

        Private Class SectorAsyncDownloadArgs
            Inherits Base.DownloadEventArgs
            Public Sectors() As Sector
            Public Sub New(ByVal userArgs As Object, ByVal sect() As Sector)
                MyBase.New(userArgs)
                Me.Sectors = sect
            End Sub
        End Class
        Private Class IndustryAsyncDownloadArgs
            Inherits Base.DownloadEventArgs
            Public Industries() As Integer
            Public Sub New(ByVal userArgs As Object, ByVal ind() As Integer)
                MyBase.New(userArgs)
                Me.Industries = ind
            End Sub
        End Class

    End Class


    ''' <summary>
    ''' Provides information and response of an asynchronous sector download.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class SectorsDownloadCompletedEventArgs
        Inherits Base.DownloadCompletedEventArgs
        Private mSectors() As Sector
        ''' <summary>
        ''' Gets the downloaded sectors.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Sectors() As Sector()
            Get
                Return mSectors
            End Get
        End Property
        ''' <summary>
        ''' Gets the response with sector information.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Response() As SectorResponse
            Get
                Return DirectCast(MyBase.Response, SectorResponse)
            End Get
        End Property
        Friend Sub New(ByVal userArgs As Object, ByVal resp As SectorResponse, ByVal sect() As Sector)
            MyBase.New(userArgs, resp)
            mSectors = sect
        End Sub
    End Class

    ''' <summary>
    ''' Provides connection information and sector information.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class SectorResponse
        Inherits Base.Response
        ''' <summary>
        ''' Gets the received sector informations.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Result() As SectorData()
            Get
                Return TryCast(MyBase.Result, SectorData())
            End Get
        End Property
        Friend Sub New(ByVal info As Base.ConnectionInfo, ByVal result As SectorData())
            MyBase.New(info, result)
        End Sub
    End Class


    ''' <summary>
    ''' Provides information and response of an asynchronous industry download.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class IndustriesDownloadCompletedEventArgs
        Inherits Base.DownloadCompletedEventArgs
        Private mIndustries() As Integer
        ''' <summary>
        ''' Gets the IDs of the downloaded industries.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public ReadOnly Property Industries() As Integer()
            Get
                Return mIndustries
            End Get
        End Property
        ''' <summary>
        ''' Gets the response with industry information
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Response() As IndustryResponse
            Get
                Return DirectCast(MyBase.Response, IndustryResponse)
            End Get
        End Property
        Friend Sub New(ByVal userArgs As Object, ByVal resp As IndustryResponse, ByVal ind() As Integer)
            MyBase.New(userArgs, resp)
            mIndustries = ind
        End Sub
    End Class

    ''' <summary>
    ''' Provides connection information and industry information.
    ''' </summary>
    ''' <remarks></remarks>
    Public Class IndustryResponse
        Inherits Base.Response
        ''' <summary>
        ''' Gets the received industry informations.
        ''' </summary>
        ''' <value></value>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Overloads ReadOnly Property Result() As IndustryData()
            Get
                Return TryCast(MyBase.Result, IndustryData())
            End Get
        End Property
        Friend Sub New(ByVal info As Base.ConnectionInfo, ByVal result As IndustryData())
            MyBase.New(info, result)
        End Sub
    End Class

End Namespace